<?php
/**
* classe pour les dates republicaines, basee sur datetimebean
* This file belongs to a webappkit package (kit)
* @link http://webappkit.net
* @package databeans
* @subpackage repdate
* @author J.Ducastel <jeremie@ducastel.name>
* @author Jose Luis Martin Mas fro conversion algorithm
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @todo fix leap years bugs for years before 1921
*/

/**
 * Date du calendrier republicain (utilise sous la revolution francaise)
 * @link http://fr.wikipedia.org/wiki/Concordance_des_dates_des_calendriers_r%C3%A9publicain_et_gr%C3%A9gorien
 * @uses DateTimeBean
 */
class RepDateBean extends DataBean {

    function RepDateBean($source=null) {
        $this->__construct($source);
    }

    function __construct($source=null) {
        // parent::__construct($source);
        $this->_greg=new DateTimeBean($source); // print_r($this->_greg);
        $this->_update();
    }

	/**
	* Return date as string, upon a format as in mysql date_format.
	* <ul>
	* <li>%% => %</li>
	* <li>%d, %e month day, 01..30</li>
	* <li>%H, %k hours, 00..23</li>
	* <li>%h, %I, %l hours, 00..12</li>
	* <li>%i minutes, 00..60</li>
	* <li>%j, year day, 001..366</li>
	* <li>%m month, 01..13</li>
	* <li>%M month name</li>
	* <li>%p AM ou PM</li>
	* <li>%s, %S seconds 00..59</li>
	* <li>%U week number, starting on sunday  00..53</li>
	* <li>%u week number, starting on monday  00..53</li>
	* <li>%W week day name</li>
	* <li>%w week day number starting on sunday, 0..6 </li>
	* <li>%y year on 2 digits</li>
	* <li>%Y year, latin letters</li>
	* </ul>
	* @param string $format as in mysql DATE_FORMAT default %Y%m%dT%H:%i:%s (iso8601)
	* @access public
	* @return string
	* @todo : D,j,l,N,s,w,z,W,h etc
	*/
	function toString($format=null) {
		if (!is_string($format))
			$format='%W %d %M an %Y';
		$format=str_replace('%Y',$this->romYear(),$format);
		$format=str_replace('%y',$this->year,$format);
		$format=str_replace('%m',sprintf('%02d',$this->mon),$format);
		$format=str_replace('%d',sprintf('%02d',$this->mday),$format);
		//$format=str_replace('%H',sprintf('%02d',$this->hours),$format);
		//$format=str_replace('%i',sprintf('%02d',$this->minutes),$format);
		//$format=str_replace('%s',sprintf('%02d',$this->seconds),$format);
		//$format=str_replace('%j',sprintf('%03d',$this->yearDay()),$format);
		//$format=str_replace('%w',sprintf('%01d',$this->weekDay()),$format);
		$format=str_replace('%M',$this->monthName(),$format);
		$format=str_replace('%W',$this->dayName(),$format);
		return $format;
	}/**/

    /**
     * @var int year annee
     */
    var $year;
    function year() {
        return $this->get('year');
    }

    /**
     * returns year in roman count
     * range is I-MMMMCMXCIX (1-4999), 1792-6791 in gregorian years
     */
    function romYear() {
        $num=$this->year;
        //I V X  L  C   D   M
        //1 5 10 50 100 500 1k
        $romans=array(
            'MMMM'=>4000,'MMM'=>3000,'MM'=>2000,'M'=>1000
            ,'CM'=>900,'DCCC'=>800,'DCC'=>700,'DC'=>600,'D'=>500
            ,'CD'=>400,'CCC'=>300,'CC'=>200,'C'=>100
            ,'XC'=>90,'LCCC'=>80,'LCC'=>70,'L'=>50
            ,'XL'=>40,'XXX'=>30,'XX'=>20,'X'=>10
            ,'IX'=>9,'VIII'=>8,'VII'=>7,'VI'=>6,'V'=>5
            ,'IV'=>4,'III'=>3,'II'=>2,'I'=>1
        );
        if ($num<1 or $num>4999) {
            trigger_error("invalid range for roman years : $num outside 1-4999");
            return false;
        }
        $str='';
        while ($num>0) {
            foreach ($romans as $rom => $val) {
                if ($num>=$val) {
                    $str.=$rom;
                    $num-=$val;
                }
            }
        }
        return $str;
        /*$rome =array("","I","II","III","IV","V","VI","VII","VIII","IX");
        $rome2=array("","X","XX","XXX","XL","L","LX","LXX","LXXX","XC");
        $rome3=array("","C","CC","CCC","CD","D","DC","DCC","DCCC","CM");
        $rome4=array("","M","MM","MMM","IVM","VM","VIM","VIIM","VIIIM","IXM");
        $str=$rome[$num%10];
        $num-=($num%10);
        $num/=10;
        $str=$rome2[$num%10].$str;
        $num-=($num%10);
        $num/=10;
        $str=$rome3[$num%10].$str;
        $num-=($num%10);
        $num/=10;
        $str=$rome4[$num%10].$str;
        return $str;*/
    }

    /**
     * @var int month, numeric 1-13 (additional 5-6 days at the end of year for 13d month)
     */
    var $mon;

    /**
     * @var string month name
     */
    var $month;
    function month() {
        return $this->get('month');
    }
    function monthName() { return $this->month(); }
    function _month_get() {
        static $months=array(
        'Vendemiaire'
        ,'Brumaire'
        ,'Frimaire'
        ,'Nivose'
        ,'Pluviose'
        ,'Ventose'
        ,'Germinal'
        ,'Floreal'
        ,'Prairial'
        ,'Messidor'
        ,'Thermidor'
        ,'Fructidor'
        ,'Sans-Culottides');
        return $months[$this->mon-1];
    }

    /**
     * @var int day of the month
     */
    var $mday;

    /**
     * @var int 1-3 number of the decade of the month
     */
    var $decade;

    /**
     * @var int 1-10 day of the decade
    */
    var $dday;

    /**
     * @var string name of the decade day
     */
    var $day;
    function day() { return $this->get('day'); }
    function dayName() { return $this->day(); }
    /**
     * days name (day of decade)
     */
    function _day_get() {
        static $days=array(
        'Primidi'
        ,'Duodi'
        ,'Tridi'
        ,'Quartidi'
        ,'Quintidi'
        ,'Sextidi'
        ,'Septidi'
        ,'Octidi'
        ,'Nonidi'
        ,'Decadi');
        if ($this->mon!=13)
            return $days[$this->dday-1];
        // Sans-culottide
        static $sansCulottides=array(
        'Vertu'
        ,'Génie'
        ,'Travail'
        ,'Opinion'
        ,'Recompenses'
        ,'Révolution');
        return $sansCulottides[$this->dday-1];
    }

    /**
     * @var int 1-366 days since the start of the year
    */
    var $yday;

    /**
     * @var string year's day dedicated thing
     */
    var $dedicated;
    function dedicated() { return $this->_dedicated_get(); }
    function _dedicated_get() {
        static $things=array('Raisin'
        ,'Safran'
        ,'Châtaigne'
        ,'Colchique'
        ,'Cheval'
        ,'Balsamine'
        ,'Carotte'
        ,'Amaranthe'
        ,'Panais'
        ,'Cuve'
        ,'Pomme'
        ,'Immortelle'
        ,'Potiron'
        ,'Réséda'
        ,'Âne'
        ,'Belle'
        ,'Citrouille'
        ,'Sarrasin'
        ,'Tournesol'
        ,'Pressoir'
        ,'Chanvre'
        ,'Pêche'
        ,'Navet'
        ,'Amaryllis'
        ,'Bœuf'
        ,'Aubergine'
        ,'Piment'
        ,'Tomate'
        ,'Orge'
        ,'Tonneau'
        ,'Pomme'
        ,'Céleri'
        ,'Poire'
        ,'Betterave'
        ,'Oie'
        ,'Héliotrope'
        ,'Figue'
        ,'Scorsonère'
        ,'Alisier'
        ,'Charrue'
        ,'Salsifis1er'
        ,'Macre'
        ,'Topinambour'
        ,'Endive'
        ,'Dindon'
        ,'Chervis'
        ,'Cresson'
        ,'Dentelaire'
        ,'Grenade'
        ,'Herse'
        ,'Bacchante'
        ,'Azerole'
        ,'Garance'
        ,'Orange'
        ,'Faisan'
        ,'Pistache'
        ,'Macjonc'
        ,'Coing'
        ,'Cormier'
        ,'Rouleau'
        ,'Raiponce'
        ,'Turneps'
        ,'Chicorée'
        ,'Nèfle'
        ,'Cochon'
        ,'Mâche'
        ,'Chou-fleur'
        ,'Miel'
        ,'Genièvre'
        ,'Pioche'
        ,'Cire'
        ,'Raifort'
        ,'Cèdre'
        ,'Sapin'
        ,'Chevreuil'
        ,'Ajonc'
        ,'Cyprès'
        ,'Lierre'
        ,'Sabine'
        ,'Hoyau'
        ,'Érable sucré'
        ,'Bruyère'
        ,'Roseau'
        ,'Oseille'
        ,'Grillon'
        ,'Pignon'
        ,'Liège'
        ,'Truffe'
        ,'Olive'
        ,'Pelle'
        ,'Tourbe'
        ,'Houille'
        ,'Bitume'
        ,'Soufre'
        ,'Chien'
        ,'Lave'
        ,'Terre végétale'
        ,'Fumier'
        ,'Salpêtre'
        ,'Fléau'
        ,'Granit'
        ,'Argile'
        ,'Ardoise'
        ,'Grès'
        ,'Lapin'
        ,'Silex'
        ,'Marne'
        ,'Pierre à chaux'
        ,'Marbre'
        ,'Van'
        ,'Pierre à plâtre'
        ,'Sel'
        ,'Fer'
        ,'Cuivre'
        ,'Chat'
        ,'Étain'
        ,'Plomb'
        ,'Zinc'
        ,'Mercure'
        ,'Crible'
        ,'Lauréole'
        ,'Mousse'
        ,'Fragon'
        ,'Perce-neige'
        ,'Taureau'
        ,'Laurier'
        ,'Amadouvier'
        ,'Mézéréon'
        ,'Peuplier'
        ,'Coignée'
        ,'Ellébore'
        ,'Brocoli'
        ,'Laurier'
        ,'Avelinier'
        ,'Vache'
        ,'Buis'
        ,'Lichen'
        ,'If'
        ,'Pulmonaire'
        ,'Serpette'
        ,'Thlaspi'
        ,'Thimele'
        ,'Chiendent'
        ,'Trainasse'
        ,'Lièvre'
        ,'Guède'
        ,'Noisetier'
        ,'Cyclamen'
        ,'Chélidoine'
        ,'Traîneau'
        ,'Tussilage'
        ,'Cornouiller'
        ,'Violier'
        ,'Troène'
        ,'Bouc'
        ,'Asaret'
        ,'Alaterne'
        ,'Violette'
        ,'Marceau'
        ,'Bêche'
        ,'Narcisse'
        ,'Orme'
        ,'Fumeterre'
        ,'Vélar'
        ,'Chèvre'
        ,'Épinard'
        ,'Doronic'
        ,'Mouron'
        ,'Cerfeuil'
        ,'Cordeau'
        ,'Mandragore'
        ,'Persil'
        ,'Cochléaria'
        ,'Pâquerette'
        ,'Thon'
        ,'Pissenlit'
        ,'Sylvie'
        ,'Capillaire'
        ,'Frêne'
        ,'Plantoir'
        ,'Primevère'
        ,'Platane'
        ,'Asperge'
        ,'Tulipe'
        ,'Poule'
        ,'Bette'
        ,'Bouleau'
        ,'Jonquille'
        ,'Aulne'
        ,'Couvoir'
        ,'Pervenche'
        ,'Charme'
        ,'Morille'
        ,'Hêtre'
        ,'Abeille'
        ,'Laitue'
        ,'Mélèze'
        ,'Ciguë'
        ,'Radis'
        ,'Ruche'
        ,'Gainier'
        ,'Romaine'
        ,'Marronnier'
        ,'Roquette'
        ,'Pigeon'
        ,'Lilas'
        ,'Anémone'
        ,'Pensée'
        ,'Myrtille'
        ,'Greffoir'
        ,'Rose'
        ,'Chêne'
        ,'Fougère'
        ,'Aubépine'
        ,'Rossignol'
        ,'Ancolie'
        ,'Muguet'
        ,'Champignon'
        ,'Hyacinthe'
        ,'Râteau'
        ,'Rhubarbe'
        ,'Sainfoin'
        ,'Bâton-d\'or'
        ,'Chamerops'
        ,'Ver'
        ,'Consoude'
        ,'Pimprenelle'
        ,'Corbeille'
        ,'Arroche'
        ,'Sarcloir'
        ,'Statice'
        ,'Fritillaire'
        ,'Bourrache'
        ,'Valériane'
        ,'Carpe'
        ,'Fusain'
        ,'Civette'
        ,'Buglosse'
        ,'Sénevé'
        ,'Houlette'
        ,'Luzerne'
        ,'Hémérocalle'
        ,'Trèfle'
        ,'Angélique'
        ,'Canard'
        ,'Mélisse'
        ,'Fromental'
        ,'Martagon'
        ,'Serpolet'
        ,'Faux'
        ,'Fraise'
        ,'Bétoine'
        ,'Pois'
        ,'Acacia'
        ,'Caille'
        ,'Œillet'
        ,'Sureau'
        ,'Pavot'
        ,'Tilleul'
        ,'Fourche'
        ,'Barbeau'
        ,'Camomille'
        ,'Chèvrefeuille'
        ,'Caille-lait'
        ,'Tanche'
        ,'Jasmin'
        ,'Verveine'
        ,'Thym'
        ,'Pivoine'
        ,'Chariot'
        ,'Seigle'
        ,'Avoine'
        ,'Oignon'
        ,'Véronique'
        ,'Mulet'
        ,'Romarin'
        ,'Concombre'
        ,'Échalote'
        ,'Absinthe'
        ,'Faucille'
        ,'Coriandre'
        ,'Artichaut'
        ,'Girofle'
        ,'Lavande'
        ,'Chamois'
        ,'Tabac'
        ,'Groseille'
        ,'Gesse'
        ,'Cerise'
        ,'Parc'
        ,'Menthe'
        ,'Cumin'
        ,'Haricot'
        ,'Orcanète'
        ,'Pintade'
        ,'Sauge'
        ,'Ail'
        ,'Vesce'
        ,'Blé'
        ,'Chalémie'
        ,'Épeautre'
        ,'Bouillon'
        ,'Melon'
        ,'Ivraie'
        ,'Bélier'
        ,'Prêle'
        ,'Armoise'
        ,'Carthame'
        ,'Mûre'
        ,'Arrosoir'
        ,'Panis'
        ,'Salicorne'
        ,'Abricot'
        ,'Basilic'
        ,'Brebis'
        ,'Guimauve'
        ,'Lin'
        ,'Amande'
        ,'Gentiane'
        ,'Écluse'
        ,'Carline'
        ,'Câprier'
        ,'Lentille'
        ,'Aunée'
        ,'Loutre'
        ,'Myrte'
        ,'Colza'
        ,'Lupin'
        ,'Coton'
        ,'Moulin'
        ,'Prune'
        ,'Millet'
        ,'Lycoperdon'
        ,'Escourgeon'
        ,'Saumon'
        ,'Tubéreuse'
        ,'Sucrion'
        ,'Apocyn'
        ,'Réglisse'
        ,'Échelle'
        ,'Pastèque'
        ,'Fenouil'
        ,'Épine vinette'
        ,'Noix'
        ,'Truite'
        ,'Citron'
        ,'Cardère'
        ,'Nerprun'
        ,'Tagette'
        ,'Hotte'
        ,'Églantier'
        ,'Noisette'
        ,'Houblon'
        ,'Sorgho'
        ,'Écrevisse'
        ,'Bigarade'
        ,'Verge'
        ,'Maïs'
        ,'Marron'
        ,'Panier'
        ,'Vertu'
        ,'Génie'
        ,'Travail'
        ,'Opinion'
        ,'Recompenses'
        ,'Révolution');
        return $things[$this->yday-1];
    }

    /**
     * @var DateTimeBean gregorian date, for internal use.
     * All vars will be computed from this.
     * @access protected
     */
    var $_greg;

    /**
     * updates public values from internal gregorian date
     * @link http://fr.wikipedia.org/wiki/Concordance_des_dates_des_calendriers_r%C3%A9publicain_et_gr%C3%A9gorien
     * @link http://personal.telefonica.terra.es/web/jlmartinmas/repcalendar/calendar.html
    */
    function _update() {
        $g=$this->_greg;
        // minus 1792
        $this->year=$g->year()-1792;
        //The Revolutionary Calendar decree didn't make it clear which years were leap years
        //There's still an open debate about the correct rule
        //After checking several sources, I've decided to follow the 4/128 rule
        //March 2007: John Hynes's (decimaltime.hynes.net) has offered me really throrough and good explanations of failures in my calculations
        //and he has made me notice that with the 4/128 rule, all Republican years since Gregorian 1920 till Gregorian 2047 should begin on Sep. 23rd
        //Considering this and that I don't think this software will be working after 2047 :) I've decided to remove my leap years calculations
        //and statically fix the first day date on 23rd
        $firstmon=9;
        if ($g->year()<1920)
            $firstday=22;
        else if ($g->year()<2048)
            $firstday=23;
        else
            $firstday=24; // not sure about this, but won't matter for now ;)
        //we must check if Gregorian date is past the Rev New Year included in
        //that Gregorian year, since then we have to add 1 to the Rev Year calculation
        //This also let us know in which Gregorian year was Rev New Year of the date
        //to calculate, something useful later
        if ((($g->mon()-$firstmon) >= 1)
        or ((($g->mon()-$firstmon) == 0) and (($g->mday()-$firstday) >= 0))) {
            $this->year++;
            $newyear=$g->year();
        } else {
            $newyear=$g->year()-1;
        }
        //now we calculate how many days have passed since Rev New Year till today
        $newYearDay=new dateTimeBean(array('year'=>$newyear,'mon'=>$firstmon,'mday'=>$firstday)); // print_r($newYearDay);
        $this->yday=floor($g->toDays()-$newYearDay->toDays())+1; // echo $this->yday;
        // final calculations for month and month's day
        $this->mon = floor($this->yday/30)+1;
        $this->mday=$this->yday%30;
        if ($this->mday == 0) {
            //30th day of month
            $this->mday = 30;
            $this->mon--; //30th day --> "jumps" to next month
        }
        if ($this->mday <= 10) {
            $this->decade = 1;
            $this->dday=$this->mday;
        } else if (($this->mday > 10) and ($this->mday <= 20)) {
            $this->decade = 2;
            $this->dday = $this->mday - 10;
        } else {
            $this->decade = 3;
            $this->dday = $this->mday - 20;
        }
    }

    /**
     * defines if a year is sextile. The rule is the same as for gregorian years
     * cf decret du 19 floreal an III (1795-05-08)
    */
    function _isSextile($year) {
        if ($year%4==0 and $year%100!=0 and $year%400==0)
            return true;
        return false;
    }
}
?>